package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.config.SMSSentValue;
import cn.itsource.ymcc.constant.ErrorConstantCode;
import cn.itsource.ymcc.constant.RedisConstants;
import cn.itsource.ymcc.dto.VerifyCodeDTO;
import cn.itsource.ymcc.exception.GlobalException;
import cn.itsource.ymcc.service.VerifyCodeService;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.util.SecurityContextUtil;
import cn.itsource.ymcc.util.StrUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * 发送短信验证码
 */
@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private SMSSentValue smsSentValue;


    @Override
    public void sendSmsCode(String phone) {
        //1. 要验证手机号，非空格式
        AssertUtil.isNotEmpty(phone,ErrorConstantCode.PHONE_NOT_EMPTY_40010);
        AssertUtil.isPhone(phone,ErrorConstantCode.PHONE_FORMATE_40020);

        //2. 根据手机号，到Redis里查询，是否发送过验证码：
        String key = String.format(RedisConstants.SMS_REGISTER_KEY,phone);
        VerifyCodeDTO  verifyCodeDTO  = (VerifyCodeDTO)redisTemplate.opsForValue().get(key);

        //3. 判断验证码对象，重新封装
        verifyCodeDTO = assertVerifyCode(verifyCodeDTO);

        //4. 把验证码保存到Redis，设置过期时间
        redisTemplate.opsForValue().set(key,verifyCodeDTO,smsSentValue.getExpirationTime(), TimeUnit.MINUTES);

        //5. 调用短信接口，提示消息日志
        String info = String.format(smsSentValue.getSendPrompt(),verifyCodeDTO.getVerifyCode(),smsSentValue.getExpirationTime());
        log.info(info);
    }


    /**
     * 创建放重token
     * @param courseId
     * @return
     */
    @Override
    public String getToken(Long courseId) {
       // key -- userid:courseids        value --- token(uuid)
        // TODO token 获取Userid
        Long loginID = SecurityContextUtil.getUserDetail().getUserId();
        String key = String.format(RedisConstants.ORDER_TOKEN_KEY,loginID,courseId);
        String value = StrUtils.getComplexRandomString(6);
        // 添加到redis,5分钟之内下单有效
        redisTemplate.opsForValue().set(key,value,5,TimeUnit.MINUTES);

        return value;

    }

    // 判断验证码对象
    private VerifyCodeDTO assertVerifyCode(VerifyCodeDTO verifyCodeDTO) {
        Date date = new Date();
        String verifyCode ="";

        //2. 1. 存在
        if(verifyCodeDTO !=null){
            //判断时间，1分钟之内，提示用户请勿重复发送
            Long oldtime = verifyCodeDTO.getCurrentTime();
            verifyCode = verifyCodeDTO.getVerifyCode();

            boolean timeBool = date.getTime() - oldtime < smsSentValue.getFrequentTime();

            AssertUtil.isFalse(timeBool,ErrorConstantCode.REPEAT_SEND_40030);
            //超过3分钟，重新设置过期时间

        }else {
            //2.2 2. 不存在
            //生成随机验证码
            verifyCode = StrUtils.getRandomString(smsSentValue.getVerifyCodeLeng());
            verifyCodeDTO = new VerifyCodeDTO(verifyCode,date.getTime());
            // 当前时间记录,1分钟请勿重复发送，3分钟复用之前的验证码
        }
        return verifyCodeDTO;
    }


}
